package info.sean.util;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 安全工具类
 *
 * @author shijian
 * @email shijian@gomefinance.com.cn
 * @date 2019-09-10
 */
public final class Safes {
    /**
     * 当参数为null返回一个不可变的空List集合, 当参数不为null时直接返回
     */
    public static <T> List<T> of(List<T> list) {
        return Optional.ofNullable(list).orElse(Collections.emptyList());
    }

    /**
     * 当参数为null返回一个不可变的空Set集合, 当参数不为null时直接返回
     */
    public static <T> Set<T> of(Set<T> set) {
        return Optional.ofNullable(set).orElse(Collections.emptySet());
    }

    /**
     * 当参数为null返回一个不可变的空Collection集合, 当参数不为null时直接返回
     */
    public static <T> Collection<T> of(Collection<T> coll) {
        return Optional.ofNullable(coll).orElse(Collections.emptySet());
    }

    /**
     * 当参数为null返回一个不可变的空迭代器, 当参数不为null时直接返回
     */
    public static <T> Iterator<T> of(Iterator<T> iter) {
        return Optional.ofNullable(iter).orElse(Collections.emptyIterator());
    }

    /**
     * 当参数为null返回一个不可变的空可迭代对象, 当参数不为null时直接返回
     */
    public static <T> Iterable<T> of(Iterable<T> iter) {
        return Optional.ofNullable(iter).orElse(Collections::emptyIterator);
    }

    /**
     * 当参数为null返回一个不可变的空Map集合, 当参数不为null时直接返回
     */
    public static <K, V> Map<K, V> of(Map<K, V> map) {
        return Optional.ofNullable(map).orElse(Collections.emptyMap());
    }

    /**
     * 当参数为null返回BigDecimal.ZERO, 当参数不为null时直接返回
     */
    public static BigDecimal of(BigDecimal bigDecimal) {
        return Optional.ofNullable(bigDecimal).orElse(BigDecimal.ZERO);
    }

    /**
     * 当参数为null返回"", 当参数不为null时直接返回
     */
    public static String of(String string) {
        return of(string, "");
    }

    /**
     * 当source为null返回defaultValue, 当source不为null时直接返回source
     */
    public static <T> T of(T source, T defaultValue) {
        return Optional.ofNullable(source).orElse(defaultValue);
    }

    /**
     * 过滤排除集合中元素为null
     * @return 如果list为null则返回不可变List集合对象
     *         如果list为空集合或集合中没有null元素则返回原来List集合对象
     *         如果存在null元素则返回新List集合对象, 新List集合对象为可变集合
     */
    public static <T> List<T> filterNull(List<T> list) {
        if (list == null) {
            return Collections.emptyList();
        }
        if (list.isEmpty()) {
            return list;
        }
        if (list.stream().allMatch(Objects::nonNull)) {
            return list;
        }
        return list.stream().filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 获取第一个元素
     */
    public static <T> T first(Collection<T> coll) {
        if (coll == null || coll.isEmpty()) {
            return null;
        }
        if (coll instanceof List) {
            return ((List<T>) coll).get(0);
        }
        return first(coll.iterator());
    }

    /**
     * 获取第一个元素
     */
    public static <T> T first(Iterable<T> iter) {
        if (iter == null) {
            return null;
        }
        return first(iter.iterator());
    }

    /**
     * 获取第一个元素
     */
    public static <T> T first(Iterator<T> iter) {
        if (iter == null) {
            return null;
        }
        if (iter.hasNext()) {
            return iter.next();
        }
        return null;
    }

    /**
     * 获取最后一个元素
     */
    public static <T> T last(Collection<T> coll) {
        if (coll == null || coll.isEmpty()) {
            return null;
        }
        if (coll instanceof List) {
            return ((List<T>) coll).get(coll.size() - 1);
        }
        return last(coll.iterator());
    }

    /**
     * 获取最后一个元素
     */
    public static <T> T last(Iterable<T> iter) {
        if (iter == null) {
            return null;
        }
        return last(iter.iterator());
    }

    /**
     * 获取最后一个元素
     */
    public static <T> T last(Iterator<T> iter) {
        if (iter == null) {
            return null;
        }
        T t = null;
        while (iter.hasNext()) {
            t = iter.next();
        }
        return t;
    }

    /**
     * 判断一个集合对象是否为null或空集合
     */
    public static boolean isEmpty(Collection<?> coll) {
        return coll == null || coll.isEmpty();
    }

    /**
     * 判断一个集合对象不为null并且非空集合
     */
    public static boolean isNotEmpty(Collection<?> coll) {
        return coll != null && !coll.isEmpty();
    }

    /**
     * 判断一个Map对象是否为null或空Map
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }

    /**
     * 判断一个Map对象不为null并且非空Map
     */
    public static boolean isNotEmpty(Map<?, ?> map) {
        return map != null && !map.isEmpty();
    }

    /**
     * 判断一个字符串对象是否为null或空串
     */
    public static boolean isEmpty(String val) {
        return val == null || val.isEmpty();
    }

    /**
     * 判断一个字符串对象不为null并且非空串
     */
    public static boolean isNotEmpty(String val) {
        return val != null && !val.isEmpty();
    }

    private Safes() throws IllegalAccessException {
        throw new IllegalAccessException("不允许实例化");
    }
}
